package com.banyuan.项目;

import java.awt.*;

import javax.swing.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class Server {

    //swing组件相关的一些属性；
    private JFrame frame;
    private JTextField textField;
    private JTextArea textArea;
    private JComboBox comboBox;
    private JTextPane textPane;

    //客户端设置的界面；
    private ServerSet serverSet;

    //客户端对象序列化输出流集合；
    private ConcurrentHashMap<String, ObjectOutputStream> outsMap;

    //定义一个set集合用来接收客户端列表；
    private Set<String> userSet;

    //新建一个Engine对象，用来接受engine，当程序退出的时候会将engine重置为null；
    private Engine engine;


    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    Server window = new Server();
                    window.frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the application.
     */
    public Server() {
        initialize();
        textArea.append("欢迎启动半圆聊天室服务端！" + "\n");
    }

    /**
     * Initialize the contents of the frame.
     */
    private void initialize() {
        frame = new JFrame();
        frame.setTitle("半圆聊天室服务端");
        frame.setBounds(100, 100, 529, 505);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().setLayout(null);

        JButton btnNewButton = new JButton("端口设置");
        btnNewButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                serverSet = new ServerSet();
                serverSet.setVisible(true);
                String s = serverSet.getPort();
                System.out.println(s);
            }
        });
        btnNewButton.setBounds(6, 6, 96, 29);
        frame.getContentPane().add(btnNewButton);

        JButton btnNewButton_1 = new JButton("启动服务");
        //多线程启动
        btnNewButton_1.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                new Thread(() -> {
                    engine = new Engine();
                }).start();
                //设置按钮不可点击；
                btnNewButton_1.setEnabled(false);
            }
        });
        btnNewButton_1.setBounds(114, 6, 96, 29);
        frame.getContentPane().add(btnNewButton_1);

        JButton btnNewButton_2 = new JButton("退出");
        btnNewButton_2.setBounds(222, 6, 96, 29);
        frame.getContentPane().add(btnNewButton_2);

        //textArea赋值;
        textArea = new JTextArea();
        JScrollPane jsp = new JScrollPane(textArea);
        jsp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        jsp.setBounds(6, 40, 517, 331);
        frame.getContentPane().add(jsp);
//        textArea.setBounds(6, 40, 517, 331);
//        frame.getContentPane().add(textArea);

        JLabel label = new JLabel("发送消息至：");
        label.setBounds(6, 383, 83, 29);
        frame.getContentPane().add(label);


        comboBox = new JComboBox();
        comboBox.setModel(new DefaultComboBoxModel(new String[]{"所有人"}));
        comboBox.setBounds(84, 383, 110, 27);
        frame.getContentPane().add(comboBox);

        JLabel label_1 = new JLabel("发送消息：");
        label_1.setBounds(6, 422, 83, 19);
        frame.getContentPane().add(label_1);

        JButton btnNewButton_3 = new JButton("发送");
        btnNewButton_3.addActionListener(new ActionListener() {
            //发送文字的事件监听器；
            //服务器的消息都是群发的；
            @Override
            public void actionPerformed(ActionEvent e) {
                Response response = new Response();
                response.setFunction(1);
                response.setMsg(textField.getText());
                textArea.append(response.getMsg() + "\n");
                //设置文本输入框清空；
                textField.setText("");

                //这边需要一个判断空指针的语句；
                if (outsMap == null) {
                    textArea.append("未有客户端连接！" + "\n");
                } else {
                    //群发服务器的文字；
                    sendAll(response);
                }
            }

        });
        btnNewButton_3.setBounds(406, 418, 117, 29);
        frame.getContentPane().add(btnNewButton_3);

        textField = new JTextField();
        textField.setBounds(61, 418, 345, 29);
        frame.getContentPane().add(textField);
        textField.setColumns(10);

        textPane = new JTextPane();
        textPane.setText("当前在线人数0");
        textPane.setBackground(SystemColor.window);
        textPane.setForeground(Color.LIGHT_GRAY);
        textPane.setBounds(6, 453, 507, 19);
        frame.getContentPane().add(textPane);
    }

    //定义一个群发的方法；
    public void sendAll(Response response) {
        //获取客户端的用户；
        Collection<ObjectOutputStream> outs = outsMap.values();
        //将response群发给客户端；
        for (ObjectOutputStream out : outs) {
            try {
                out.writeObject(response);
            } catch (IOException ioException) {
                ioException.printStackTrace();
            }
        }
    }

    //写一个群发的方法，并定义一个String数组，数组中的元素将不会被发送；
    public void sendAllExcept(Response response, String[] arr) {
        //获取客户端的用户名；
        Collection<String> user = outsMap.keySet();

        for (String s : user) {
            //定义标志位
            boolean flag = false;
            for (String s1 : arr) {
                flag = s1.equals(s);
                if (flag)
                    break;
            }
            if (!flag) {
                try {
                    outsMap.get(s).writeObject(response);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    //定义一个单发的功能；
    public void sendSomeone(Response response, String userName) {
        ObjectOutputStream out = outsMap.get(userName);
        try {
            out.writeObject(response);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //一个新建的内部类，这个在按钮启动点下去的时候，或新建一个内部类，这个是在所有的按钮之前要按下去，可以在所有的按钮之前追加一个判断；
    public class Engine {
        private int index;

        public Engine() {
            try {
                ServerSocket serverSocket = new ServerSocket(8080);
                textArea.append("服务器已启动，正在监听，等待客户端连接！" + "\n");
                outsMap = new ConcurrentHashMap<String, ObjectOutputStream>();

                while (true) {
                    //等待客户端连接，处于阻塞状态
                    Socket socket = serverSocket.accept();
                    textArea.append("客户端已连接！");
                    //建立序列化的输出流；
                    ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
                    //接受过来的信息
                    ObjectInputStream in = new ObjectInputStream(socket.getInputStream());

                    new Thread(() -> {
                        try {
                            while (true) {
//                                textArea.append("反序列化输入流：" + "\n");
                                Request request = null;
                                Object o = in.readObject();
//                                textArea.append("强转过程！" + "\n");
                                request = (Request) o;
//                                textArea.append("选择界面！" + "\n");

                                switch (request.getFunction()) {
                                    //登陆
                                    case 1:
                                        //保存用户名的信息和输出的端口；
                                        outsMap.put(request.getUsername(), out);
                                        textArea.append("客户端" + request.getUsername() + "已连接！" + "\n");
                                        userSet = outsMap.keySet();
                                        //更新服务器的发送人列表；
                                        Vector<String> v = new Vector<>(userSet);
                                        v.add("所有人");
                                        comboBox.setModel(new DefaultComboBoxModel(v));

                                        //更新服务器在线人数；
                                        int numClient = outsMap.size();
                                        textPane.setText("当前在线人数：" + numClient);
//                                        textArea.append("对话列表已更新！");
                                        //在每一次登陆的情况下将该列表发送给每个客户端；
                                        //设置response；

                                        Response response = new Response();
                                        response.setFunction(2);
                                        response.setV(v);
                                        response.setNumClient(numClient);
                                        //群发response更新客户端的列表；
                                        sendAll(response);

//                                        textArea.append("客户端列表已发送更新！");

                                        break;

                                    //退出
                                    case 2:
                                        break;

                                    //注销
                                    case 3:
                                        break;

                                    //发送消息
                                    case 4:
                                        textArea.append("已进入选项4：" + "\n");
                                        //接收是否私聊的信息；
                                        boolean b = request.isAll();
                                        //接收是所有人还是单个；
                                        String s = request.getTo();

                                        Response response4 = new Response();
                                        //获取到信息；
                                        response4.setMsg(request.getMsgOut());
                                        //获取到表情；
                                        response4.setExpression(request.getExpression());
                                        //设置发送者的姓名；
                                        response4.setUserName(request.getUsername());
                                        if (b) {
                                            //私聊的功能设置为response的功能3；
                                            response4.setFunction(3);
                                            if (s.equals("所有人")) {
                                                //私聊所有人；
                                                //群发；
                                                sendAll(response4);
                                                if (request.getExpression().equals("无")) {
                                                    textArea.append(request.getUsername() + "悄悄地对大家说：" + request.getMsgOut() + "\n");
                                                } else {
                                                    textArea.append(request.getUsername() + "（" + request.getExpression() + "）" + "悄悄地对大家说：" + request.getMsgOut() + "\n");
                                                }
                                            } else {
                                                //私信单个人；
                                                //获取到该ID的输出流；
                                                sendSomeone(response4, s);
                                                //打印到服务器的文本域；
                                                if (request.getExpression().equals("无")) {
                                                    textArea.append(request.getUsername() + "悄悄的对" + request.getTo() + "说：" + request.getMsgOut() + "\n");
                                                } else {
                                                    textArea.append(request.getUsername() + "（" + request.getExpression() + "）" + "悄悄的对" + request.getTo() + "说：" + request.getMsgOut() + "\n");

                                                }
                                            }
                                        } else {
                                            //非私聊的过程；
                                            if (s.equals("所有人")) {
                                                //设置非私聊的群发过程是功能4；
                                                response4.setFunction(4);
                                                //群发的过程中将原来的用户排除在外面；
                                                sendAllExcept(response4, new String[]{request.getUsername()});
                                                if (request.getExpression().equals("无")) {
                                                    textArea.append(request.getUsername() + "对大家说：" + request.getMsgOut() + "\n");
                                                } else {
                                                    textArea.append(request.getUsername() + "（" + request.getExpression() + "）" + "对大家说：" + request.getMsgOut() + "\n");
                                                }
                                            } else {
                                                //非私聊的单独的对话；
                                                response4.setFunction(5);
                                                response4.setTo(s);
                                                //服务器将回应所有用户，除了发送者和接受者；

                                                //排除发送者和接受者；
                                                sendAllExcept(response4, new String[]{request.getUsername(), request.getTo()});

                                                //建立一个新的回应；
                                                //回应里面需要设置function，userName,expression,msg;
                                                Response response4_1 = new Response();
                                                response4_1.setFunction(6);
                                                response4_1.setUserName(request.getUsername());
                                                response4_1.setExpression(request.getExpression());
                                                response4_1.setMsg(request.getMsgOut());

                                                //单独向接受者发送一个response；
                                                sendSomeone(response4_1, request.getTo());

                                                //服务端文本域输出；
                                                if (request.getExpression().equals("无")) {
                                                    textArea.append(request.getUsername() + "对" + request.getTo() + "说：" + request.getMsgOut() + "\n");
                                                } else {
                                                    textArea.append(request.getUsername() + "（" + request.getExpression() + "）" + "对" + request.getTo() + "说：" + request.getMsgOut() + "\n");
                                                }
                                            }
                                        }
                                        break;
                                }

                            }
                        } catch (ClassNotFoundException e) {
                            e.printStackTrace();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }).start();
                }


            } catch (IOException e) {
                e.printStackTrace();
            }


        }
    }
}
